﻿using System;
using System.Linq;
using System.Xml;
using System.Net;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Practices.Prism.Regions;
using Microsoft.Practices.Prism.Events;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Unity;
using DXTools.UI.Core;
using DXTools.UI.Modules.Configuration.Views;
using DXTools.UI.Core.Events;
using System.Collections.Generic;
using DXTools.UI.Core.ViewModel;
using System.Collections.ObjectModel;
using System.Text;
using DXTools.UI.Core.DataProviders;
using DXTools.Core.CrmSdk;
using DXTools.UI.Core.Model;
using DXTools.Core.Model;
using DXTools.Core.Enum;
using DXTools.UI.Modules.Configuration.Model;
using DXTools.UI.Modules.Configuration.Events;
using System.Xml.Linq;


namespace DXTools.UI.Modules.Configuration.ViewModels
{
    public class InstalledToolsViewModel : ViewModelBase
    {
        #region Private Attributes
        private const string HEADER_INFO = "Installed Tools";
        private ICRMDataProvider crmDataProvider;
        #endregion

        #region Properties

        private ObservableCollection<Tool> _toolList;
        public ObservableCollection<Tool> ToolList
        {
            get
            {
                return _toolList;
            }
            set
            {
                _toolList = value;
                RaisePropertyChanged("ToolList");
            }
        }

        private IOrderedEnumerable<Tool> _filteredToolList;
        public IOrderedEnumerable<Tool> FilteredToolList
        {
            get
            {
                return _filteredToolList;
            }
            set
            {
                _filteredToolList = value;
                RaisePropertyChanged("FilteredToolList");
            }
        }

        private String _searchText;
        public String SearchText
        {
            get
            {
                return _searchText;
            }
            set
            {
                _searchText = value;
                RaisePropertyChanged("SearchText");
            }
        }

        
        #endregion

        #region Constructors

         public InstalledToolsViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer container)
            :base(regionManager,eventAggregator,container)
        {
            this.HeaderInfo = HEADER_INFO;

            this.CloseViewCommand = new DelegateCommand<object>(this.CloseView, this.CanCloseView);
            this.SearchCommand = new DelegateCommand<object>(this.Search, this.CanSearch);

            crmDataProvider = new CRMDataProvider();

            //eventAggregator.GetEvent<UpdateStatusEvent>().Subscribe(UpdateToolsStatus);

            RetrieveInstalledTools();
            




        }

        #endregion

        #region Retrieve Installed Tools

        private void RetrieveInstalledTools()
         {

             AsyncCallback asyncCallback = (result =>
             {
                 IOrganizationService service = (IOrganizationService)result.AsyncState;
                 EntityCollection response = service.EndRetrieveMultiple(result);
                 ObservableCollection<Tool> tools = new ObservableCollection<Tool>();
                 Action method = () =>
                 {
                     foreach (Entity e in response.Entities)
                     {
                         if (e.Attributes.ContainsKey("uniquename"))
                         {
                             string name = e["uniquename"] as string;
                             //if (name.Contains("XRMTools"))
                             //{
                                 tools.Add(
                                     new Tool()
                                    {
                                        
                                        Name = name
                                        ,
                                        DisplayName = e.Attributes.ContainsKey("friendlyname") ? e["friendlyname"] as string : string.Empty
                                        ,
                                        Version = e.Attributes.ContainsKey("version") ? e["version"] as string : string.Empty
                                        ,
                                        Enable = true //Set according to User Settings
                                    }
                                );
                             ///}
                         }
                     }
                     this.ToolList = tools;
                     this.FilteredToolList = from t in tools orderby t.DisplayName select t;
                     

                     CheckDownloadableToolsForNewerVersions();
                 };

                 this.View.Dispatcher.BeginInvoke(method);

             });

             this.IsBusy = true;
             this.crmDataProvider.RetrieveSolutionList(asyncCallback);
         }


        private void CheckDownloadableToolsForNewerVersions()
        {
            WebRequest GETRequest = null;

            AsyncCallback asyncCallback = (result =>
            {
                Action method = () =>
                {
                  

                    WebResponse GETResponse = GETRequest.EndGetResponse(result);

                   
                    XDocument doc = XDocument.Load(GETResponse.GetResponseStream(), LoadOptions.SetBaseUri);
                    foreach (XElement module in doc.Root.Elements())
                    {
                           string name = module.Element(XName.Get("Name", "http://schemas.datacontract.org/2004/07/DXTools.Service.Configuration")).Value;
                           string version = module.Element(XName.Get("Version", "http://schemas.datacontract.org/2004/07/DXTools.Service.Configuration")).Value;

                           foreach (Tool tool in this.ToolList)
                           {
                               if (tool.Name == name && CompareVersions(tool.Version, version) < 0)
                               {
                                   tool.NewVersion = version;
                                   break;
                               }
                           }
                    }
                    this.ToolList = this.ToolList;
                    this.FilteredToolList = from t in this.ToolList orderby t.DisplayName select t;
                     

                    this.IsBusy = false;
                };

                this.View.Dispatcher.BeginInvoke(method);
            });

            GETRequest = DXTools.Core.Service.ConfigService.RetrieveModules(asyncCallback);
        }

        /// <summary> 
        /// Compare versions of form "1.2.3.4". Throws FormatException 
        /// in case of invalid version. 
        /// </summary> 
        /// <param name="strA">the first version</param> 
        /// <param name="strB">the second version</param> 
        /// <returns>less than zero if strA is less than strB, equal to zero if 
        /// strA equals strB, and greater than zero if strA is greater than strB</returns> 
        public static int CompareVersions(String strA, String strB)
        {
            Version vA = new Version(strA);
            Version vB = new Version(strB);

            return vA.CompareTo(vB);
        } 


        #endregion

        #region Close

         private void CloseView(object commandArg)
         {
             base.CloseView();
         }
         private bool CanCloseView(object commandArg)
         {
             return true;
         }       

        #endregion

        #region Search
        
        public DelegateCommand<object> SearchCommand { get; private set; }

        private bool CanSearch(object commandArg)
         {
             return true;
         }

        private void Search(object commandArg)
         {
             string text = Convert.ToString(commandArg);
             if (!String.IsNullOrEmpty(text))
                 SearchText = text;

             if (!String.IsNullOrEmpty(SearchText))
             {
                 this.FilteredToolList = from t 
                                         in ToolList
                                         where t.DisplayName.ToLowerInvariant().Contains(SearchText.ToLowerInvariant())
                                         orderby t.DisplayName 
                                         select t;
             }
             else
                 this.FilteredToolList = from t in ToolList orderby t.DisplayName select t;


         }

        #endregion

        #region Update Tools Status

        public void UpdateToolsStatus(string eventArg)
        {
            MessageBox.Show("uooo");
        }

        #endregion


    }
}
